package com.zjb.demo.system.service;

import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.solon.service.impl.ServiceImpl;
import com.zjb.demo.common.domain.response.TreeSelect;
import com.zjb.demo.common.exception.ServiceException;
import com.zjb.demo.common.util.SecurityUtils;
import com.zjb.demo.system.domain.SysDept;
import com.zjb.demo.system.domain.dto.SysDeptPageQueryDto;
import com.zjb.demo.system.domain.query.SysDeptQuery;
import com.zjb.demo.system.mapper.SysDeptMapper;
import com.zjb.demo.system.mapper.SysRoleMapper;
import com.zjb.demo.system.mapper.UserMapper;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.zjb.demo.system.domain.table.SysDeptTableDef.SYS_DEPT;
import static com.zjb.demo.system.domain.table.UserTableDef.USER;

/**
 * @author 庄佳彬
 * @since 2023/12/27 22:37
 */
@Component
public class SysDeptService extends ServiceImpl<SysDeptMapper, SysDept> {
    @Inject
    private UserMapper userMapper;

    @Inject
    private SysRoleMapper roleMapper;

    @Inject
    private SysDeptMapper deptMapper;

    /**
     * 根据查询条件分页查询部门信息
     *
     * @param query 查询条件
     * @return 分页结果
     */
    public Page<SysDept> pageList(SysDeptQuery query) {
        var page = new Page<SysDept>(query.getPageNum(), query.getPageSize());
        return mapper.pageList(new SysDeptPageQueryDto(query.getDeptId(), query.getParentId(), query.getDeptName(), query.getStatus(), page)); // 分页返回结果
    }

    /**
     * 检查部门数据权限
     *
     * @param deptId 部门ID
     */
    public void checkDeptDataScope(Long deptId) {
        var userId = SecurityUtils.getUserId();
        if (userId != 1L) {
            var dept = getById(deptId);
            if (dept == null) {
                throw new ServiceException("没有权限访问部门数据!");
            }
        }
    }

    /**
     * 检查部门名称是否唯一
     *
     * @param sysDept 系统部门对象
     * @return 部门名称是否唯一
     */
    public boolean checkDeptNameUnique(SysDept sysDept) {
        var query = QueryWrapper.create()
                .where(SYS_DEPT.DEPT_NAME.eq(sysDept.getDeptName()))
                .and(SYS_DEPT.PARENT_ID.eq(sysDept.getParentId()));
        return this.exists(query);
    }

    /**
     * 根据部门ID查询普通子部门（正常状态数量）
     *
     * @param deptId 部门ID
     * @return 选择的普通子部门
     */
    public long selectNormalChildrenDeptById(Long deptId) {
        return mapper.selectNormalChildrenDeptById(deptId);
    }

    /**
     * 判断是否存在指定部门Id的子部门
     *
     * @param deptId 部门Id
     * @return true 存在子部门 false 不存在子部门
     */
    public boolean hasChildByDeptId(Long deptId) {
        var query = QueryWrapper.create()
                .where(SYS_DEPT.PARENT_ID.eq(deptId));
        return this.exists(query);
    }


    /**
     * 检查部门是否存在用户
     *
     * @param deptId 部门ID
     * @return 如果部门存在用户则返回true，否则返回false
     */
    public boolean checkDeptExistUser(Long deptId) {
        var query = QueryWrapper.create()
                .select(USER.ID)
                .from(USER)
                .where(USER.DEPT_ID.eq(deptId));
        return userMapper.selectCountByQuery(query) > 0;
    }

    public List<TreeSelect> selectDeptTreeList() {
        var list = list();
        return buildDeptTreeSelect(list);
    }

    public List<TreeSelect> selectDeptTreeList(SysDept dept) {

        var list = mapper.list(new SysDeptPageQueryDto(dept.getDeptId(), dept.getParentId(), dept.getDeptName(), dept.getStatus()));
        return buildDeptTreeSelect(list);
    }

    private List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts) {
        List<SysDept> deptTrees = buildDeptTree(depts);
        return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    private List<SysDept> buildDeptTree(List<SysDept> depts) {
        List<SysDept> returnList = new ArrayList<>();
        List<Long> tempList = depts.stream().map(SysDept::getDeptId).toList();
        for (SysDept dept : depts) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId())) {
                recursionFn(depts, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty()) {
            returnList = depts;
        }
        return returnList;
    }

    private void recursionFn(List<SysDept> list, SysDept t) {
        // 得到子节点列表
        List<SysDept> childList = getChildList(list, t);
        t.getChildren().addAll(childList);
        for (SysDept tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    private List<SysDept> getChildList(List<SysDept> list, SysDept t) {
        List<SysDept> tlist = new ArrayList<>();
        for (SysDept n : list) {
            if (!Objects.isNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    private boolean hasChild(List<SysDept> list, SysDept t) {
        return !getChildList(list, t).isEmpty();
    }

    /**
     * 根据角色ID查询部门列表
     *
     * @param roleId 角色ID
     * @return 部门列表
     */
    public List<Long> selectDeptListByRoleId(Long roleId) {
        return roleMapper.selectOneById(roleId)
                .map(role -> deptMapper.selectDeptListByRoleId(roleId, role.getDeptCheckStrictly())).orElse(Collections.emptyList());
    }

}
